home *** CD-ROM | disk | FTP | other *** search
/ Ian & Stuart's Australian Mac 1993 September / September 93.iso / Archives / Comunications / telecom / Telecom Utilities / Modem Initializer 1.1 / Modem CDev.pas next >
Encoding:
Pascal/Delphi Source File  |  1991-04-18  |  43.7 KB  |  954 lines  |  [TEXT/PJMM]

  1. {-------------------------------------------------------------------------------    }
  2. {            Modem Initializer  ©1991  Mountainside Software  by Tim Damon                }
  3. {This cdev/INIT was written exclusively for my entertainment and education of Mac        }
  4. {programming.  I do not offer any warrenty or upgrades to this product as it is meant    }
  5. {purley to be an example of programming a control panel device with an init.  If you use    }
  6. {this source code to write your own cdev or INIT,  please at least give me some credit    }
  7. {for my hard work.  I am willing to answer any questions you may have about this        }
  8. {program and will do my best to answer any questions you may have about writing your    }
  9. {own cdev/INIT.  I learned quite a bit from writing this and may be able to help you out.    }
  10. {If you need to contact me or want to send me something like $$$$ or a postcard,  send    }
  11. {paper mail to:                                                                                    }
  12. {Tim Damon                                                                                        }
  13. {3305 Parade Circle East                                                                        }
  14. {Colo. Spgs.,  CO  80917                                                                            }
  15. {or comments or questions electronically to:                                                    }
  16. {America Online: Screen Name- Yimmit                                                        }
  17. {GEnie: T.Damon                                                                                    }
  18. {I really hope this helps you programmers out in the area of cdev's and/or INIT's.            }
  19. {Good Luck!                                                                                        }
  20. {-------------------------------------------------------------------------------    }
  21.  
  22.  
  23. unit ModemCDEV;
  24.  
  25. interface
  26.     uses
  27.         serial;
  28.  
  29.     const
  30.         ERRDLOG = -4034;        {ID # of the error dialog}
  31.  
  32.         G11200 = 1;                {Item number of the radio button for 1200 baud rate}
  33.         G12400 = 2;                {Item number of the radio button for 2400 baud rate}
  34.         G19600 = 3;                {Item number of the radio button for 9600 baud rate}
  35.         G2NO = 4;                    {Item number of the radio button for no parity}
  36.         G2EVEN = 5;                {Item number of the radio button for even parity}
  37.         G2ODD = 6;                {Item number of the radio button for odd parity}
  38.         G31 = 7;                    {Item number of the radio button for 1 stop bit}
  39.         G312 = 8;                    {Item number of the radio button for 1.5 stop bits}
  40.         G32 = 9;                    {Item number of the radio button for 2 stop bits}
  41.         G47 = 10;                    {Item number of the radio button for 7 data bits}
  42.         G48 = 11;                    {Item number of the radio button for 8 data bits}
  43.         COMMLINE = 12;            {Item number of the Command Line}
  44.         SENDNOW = 13;            {Item number of the button to do modem initialization now}
  45.         MICON = 14;                {Item number of the modem ICON}
  46.         PICON = 15;                {Item number of the printer ICON}
  47.  
  48.         BAUD12 = 1;                {Value SERC resource holds for 1200 baud rate after decoding}
  49.         BAUD24 = 2;                {Value SERC resource holds for 2400 baud rate after decoding}
  50.         BAUD96 = 4;                {Value SERC resource holds for 9600 baud rate after decoding}
  51.         PARNONE = 32;            {Value SERC resource holds for no parity after decoding}
  52.         PAREVEN = 64;            {Value SERC resource holds for even parity after decoding}
  53.         PARODD = 128;            {Value SERC resource holds for odd parity after decoding}
  54.         STOP1 = 4;                {Value SERC resource holds for 1 stop bit after decoding}
  55.         STOP12 = 8;                {Value SERC resource holds for 1.5 stop bits after decoding}
  56.         STOP2 = 16;                {Value SERC resource holds for 2 stop bits after decoding}
  57.         DAT7 = 1;                {Value SERC resource holds for 7 data bits after decoding}
  58.         DAT8 = 2;                {Value SERC resource holds for 8 data bits after decoding}
  59.  
  60. {cdev message numbers}
  61.         initDev = 0;                {Initialize the cdev}
  62.         hitDev = 1;                {Handle a hit on an item}
  63.         closeDev = 2;                {Close down the cdev}
  64.         nulDev = 3;                {Desk accessory run}
  65.         updateDev = 4;            {Update any items that the dialog manager won't}
  66.         activDev = 5;                {Control Panel becoming active again}
  67.         deActivDev = 6;            {Control Panel becoming inactive}
  68.         keyEvtDev = 7;            {A keypress happened with the Control Panel active}
  69.         macDev = 8;                {Sent if 'mach' resource doesn't contain a specific machine setting}
  70.         undoDev = 9;                {Text edit Undo}
  71.         cutDev = 10;                {Text edit Cut}
  72.         copyDev = 11;            {Text edit Copy}
  73.         pasteDev = 12;            {Text edit Paste}
  74.         clearDev = 13;            {Text edit Clear}
  75.         cursorDev = 14;            {Sent if 'CURS' ID -4064 resource is present - allows your own cursors in the cdev}
  76. {****For more inofromation on cursorDev refer to TN #215****}
  77.  
  78.         F1 = $7A;                    {Key code for undo function key on an extended keyboard}
  79.         F2 = $78;                    {Key code for cut function key on an extended keyboard}
  80.         F3 = $63;                    {Key code for copy function key on an extended keyboard}
  81.         F4 = $76;                    {Key code for paste function key on an extended keyboard}
  82.  
  83.     type
  84.  
  85.         ButtonRec = record            {A record to hold the state of each group}
  86.                 value: integer;            {The value of this group}
  87.                 item: integer;                {The item number of the button that is set in the group}
  88.             end;
  89.  
  90.         GroupRec = record
  91.                 Group1: ButtonRec;            {This is the radio button for Group 1 (baud rate)}
  92.                 Group2: ButtonRec;            {This is the radio button for Group 1 (parity)}
  93.                 Group3: ButtonRec;            {This is the radio button for Group 1 (stop bits)}
  94.                 Group4: ButtonRec;            {This is the radio button for Group 1 (data bits)}
  95.                 CommandText: Str255;        {This has to be part of our storage area to maintain a current copy}
  96.                 ModemPort: Boolean;        {This is the port that will be used in transmissions-->True = modem  False = printer}
  97.             end;
  98.  
  99.         GroupPtr = ^GroupRec;
  100.         GroupHnd = ^GroupPtr;        {This will be a handle to the GroupRec}
  101.  
  102.         SerConRec = record
  103.                 baudRateNPort: Signedbyte;    {This will hold the byte containing the baud rate & Port setting when we read it from the resource}
  104.                 rest: Signedbyte;            {This will hold the encoded byte for parity, stop bits and data bits after reading the resource}
  105.             end;
  106.         SerConPtr = ^SerConRec;
  107.         SerConHnd = ^SerConPtr;    {This will be a handle to the serial configuration record}
  108.  
  109.     function main (message, item, numItems, CPanelID: INTEGER; var theEvent: EventRecord; cdevStorage: Longint; CPDialog: DialogPtr): Longint;
  110.  
  111. implementation
  112.  
  113. {All of these forward declarations are neccesary in order to keep 'main' as the first code in the code resource}
  114.  
  115. {==================================================================================}
  116.     procedure ReadResources (var CommandLine: StringHandle; var ConfigHnd: SerConHnd);
  117.     forward;
  118.  
  119.     procedure DecodeConfigResource (ConfigHnd: SerConHnd; var Baud, Par, StopB, DataB, Port: integer);
  120.     forward;
  121.  
  122.     procedure SetButtonON (var ThisButton: ButtonRec; CPDialog: DialogPtr; numItems: integer);
  123.     forward;
  124.  
  125.     procedure SetButtonOFF (var ThisButton: ButtonRec; CPDialog: DialogPtr; numItems: integer);
  126.     forward;
  127.  
  128.     procedure SetUpButtons (var GroupRecord: GroupHnd; Baud, Par, StopB, DataB: integer);
  129.     forward;
  130.  
  131.     procedure SetCommandLine (CPDialog: DialogPtr; CommandLine: StringHandle; numItems: integer);
  132.     forward;
  133.  
  134.     procedure DoClose (var cdevStorage: Longint);
  135.     forward;
  136.  
  137.     procedure DoHit (var cdevStorage: Longint; var GroupRecord: GroupHnd; ItemHit: integer; CPDialog: DialogPtr; numItems: integer);
  138.     forward;
  139.  
  140.     procedure GetGroupValues (GroupRecord: GroupHnd; var Baud, Par, StopB, DataB: integer);
  141.     forward;
  142.  
  143.     procedure EncodeResource (var ConfigHnd: SerConHnd; Baud, Par, StopB, DataB: integer; ModemPort: Boolean);
  144.     forward;
  145.  
  146.     procedure SaveResources (CommandLine: StringHandle; ConfigHnd: SerConHnd);
  147.     forward;
  148.  
  149.     procedure StoreCommandLine (CPDialog: DialogPtr; CommandItem: integer; var GroupRecord: GroupHnd);
  150.     forward;
  151.  
  152.     procedure DoKeyDown (var theEvent: EventRecord; var message: integer; CPDialog: DialogPtr; numItems: integer; var GroupRecord: GroupHnd);
  153.     forward;
  154.  
  155.     procedure DoEdit (message, numItems: INTEGER; CPDialog: DialogPtr; var GroupRecord: GroupHnd);
  156.     forward;
  157. {=======================================================================================}
  158.  
  159. {The main entry point MUST be the first code of the cdev}
  160.  
  161.     function main (message, Item, numItems, CPanelID: integer; var theEvent: EventRecord; cdevStorage: Longint; CPDialog: DialogPtr): Longint;
  162.  
  163.         var
  164.             TempH: Handle;                                {A temporary handle used in GetDItem calls}
  165.             dummyKind: integer;                        {Dummy integer for use in GetDItem calls}
  166.             r: Rect;                                        {Dummy rect for use in GetDItem calls}
  167.             CommandLine: StringHandle;                {A handle to the command line read from the resource}
  168.             ConfigHnd: SerConHnd;                        {A handle to the serial configuration read from the 'SERC' resource}
  169.             Baud, Par, StopB, DataB, Port: integer;        {Used to hold values when working with decoded 'SERC' resource}
  170.             theKey: integer;                            {Used to hold a key code for a key down event}
  171.             IBeam: CursHandle;                        {Holds the IBeam cursor resource}
  172.             pt: point;                                    {Used in checking the mouse location to determine what cursor to use}
  173.             WIcon: integer;                                {The item number of the port icon hilited}
  174.  
  175.     begin
  176.         if (cdevStorage <> 1) and (cdevStorage <> 0) and (cdevStorage <> -1) then        {Check for an error}
  177.             begin                    {No error so proceed with finding what message was sent and take appropriate action}
  178.                 case message of
  179.                     initDev: 
  180.                         begin            {Initialize the cdev}
  181.                             ReadResources(CommandLine, ConfigHnd);                                        {Read the resources into memory}
  182.                             cdevStorage := ord4(NewHandle(SIZEOF(GroupRec)));                    {Set up the storage for the record of radio groups}
  183.                             DecodeConfigResource(ConfigHnd, Baud, Par, StopB, DataB, Port);            {Decode the configuration resource}
  184.                             GroupHnd(cdevStorage)^^.ModemPort := (Port = 16);                            {Set the modem port flag}
  185.                             SetUpButtons(GroupHnd(cdevStorage), Baud, Par, StopB, DataB);                {Set up each group's state}
  186.                             SetButtonON(GroupHnd(cdevStorage)^^.Group1, CPDialog, numItems);        {Set the button for Group 1}
  187.                             SetButtonON(GroupHnd(cdevStorage)^^.Group2, CPDialog, numItems);        {Set the button for Group 2}
  188.                             SetButtonON(GroupHnd(cdevStorage)^^.Group3, CPDialog, numItems);        {Set the button for Group 3}
  189.                             SetButtonON(GroupHnd(cdevStorage)^^.Group4, CPDialog, numItems);        {Set the button for Group 4}
  190.                             SetCommandLine(CPDialog, CommandLine, numItems);            {Put the command line text in the dialog}
  191.                             StoreCommandLine(CPDialog, COMMLINE + numItems, GroupHnd(cdevStorage));
  192.                         {Store the command line in our storage area}
  193.  
  194.                             ReleaseResource(Handle(CommandLine));        {We are done with this resource, let it go}
  195.                             ReleaseResource(Handle(ConfigHnd));            {We are done with this resource, let it go}
  196.                             main := cdevStorage;            {Set a return value}
  197.                         end;
  198.  
  199.                     hitDev: 
  200.                         begin            {An item was hit}
  201.                             Hlock(Handle(cdevStorage));
  202.                             DoHit(cdevStorage, GroupHnd(cdevStorage), Item - numItems, CPDialog, numItems);
  203.                             {If an item was hit, let DoHit take care of it}
  204.                             HUnlock(Handle(cdevStorage));
  205.                             main := cdevStorage;            {Set a return value}
  206.                         end;
  207.  
  208.                     closeDev: 
  209.                         begin                        {Prepare for close up}
  210.                             DoClose(cdevStorage);
  211.                             DisposHandle(Handle(cdevStorage));            {Get rid of the handle so the control panel doesn't go BOOM!}
  212.                             cdevStorage := 0;            {Set a return value}
  213.                             Main := 0;
  214.                         end;
  215.  
  216.                     deActivDev: 
  217.                         begin
  218.                             Hlock(Handle(cdevStorage));
  219.                             ReadResources(CommandLine, ConfigHnd);
  220.                         {First read the resources into memory so we have current handles for writing}
  221.                             HLock(Handle(CommandLine));                {Lock it down so it doesn't get trashed before we can write out}
  222.                             HLock(Handle(ConfigHnd));                    {Lock it down so it doesn't get trashed before we can write out}
  223.                             GetGroupValues(GroupHnd(cdevStorage), Baud, Par, StopB, DataB);                    {Get the current settings}
  224.                             EncodeResource(ConfigHnd, Baud, Par, StopB, DataB, GroupHnd(cdevStorage)^^.ModemPort);
  225.                                     {Encode the resource so it can be written}
  226.                             HUnLock(Handle(CommandLine));            {Unlock it now so we can change it}
  227.  
  228.                             if ord(GroupHnd(cdevStorage)^^.CommandText[Length(GroupHnd(cdevStorage)^^.CommandText)]) <> 13 then
  229.                                 GroupHnd(cdevStorage)^^.CommandText := concat(GroupHnd(cdevStorage)^^.CommandText, Chr(13));
  230.                                 {If there isn't a <CR> at the end of the command line, put one on}
  231.  
  232.                             SetString(CommandLine, GroupHnd(cdevStorage)^^.CommandText);                    {Set the new Command line}
  233.                             HLock(Handle(CommandLine));                {Lock it down again so it doesn't get trashed before we can write out}
  234.                             ChangedResource(Handle(CommandLine));                            {Mark resource as changed so it will be written out}
  235.                             SaveResources(CommandLine, ConfigHnd);                            {Write out the resources}
  236.                             HUnLock(Handle(CommandLine));            {Let it go now since we don't need it anymore}
  237.                             HUnLock(Handle(ConfigHnd));                {Let it go now since we don't need it anymore}
  238.                             HUnlock(Handle(cdevStorage));
  239.                             Main := cdevStorage;            {Set a return value}
  240.                         end;
  241.  
  242.                     activDev: 
  243.                         begin
  244.                             HLock(Handle(cdevStorage));
  245.                             ReadResources(CommandLine, ConfigHnd);                                            {Read the resources into memory}
  246.                             DecodeConfigResource(ConfigHnd, Baud, Par, StopB, DataB, Port);                {Decode the configuration resource}
  247.                             SetUpButtons(GroupHnd(cdevStorage), Baud, Par, StopB, DataB);                    {Set up each group's state}
  248.                             SetButtonON(GroupHnd(cdevStorage)^^.Group1, CPDialog, numItems);            {Set the button for Group 1}
  249.                             SetButtonON(GroupHnd(cdevStorage)^^.Group2, CPDialog, numItems);            {Set the button for Group 2}
  250.                             SetButtonON(GroupHnd(cdevStorage)^^.Group3, CPDialog, numItems);            {Set the button for Group 3}
  251.                             SetButtonON(GroupHnd(cdevStorage)^^.Group4, CPDialog, numItems);            {Set the button for Group 4}
  252.                             SetCommandLine(CPDialog, CommandLine, numItems);                                {Put the command line text in the dialog}
  253.                             StoreCommandLine(CPDialog, COMMLINE + numItems, GroupHnd(cdevStorage));
  254.                         {Store the command line in our storage area}
  255.  
  256.                             ReleaseResource(Handle(CommandLine));                            {We are done with this resource, let it go}
  257.                             ReleaseResource(Handle(ConfigHnd));                                {We are done with this resource, let it go}
  258.                             HUnlock(Handle(cdevStorage));
  259.                             main := cdevStorage;                                                    {Set a return value}
  260.                         end;
  261.  
  262.                     keyEvtDev:                                            {respond to key down}
  263.                         begin
  264.                             HLock(Handle(cdevStorage));
  265.                             DoKeyDown(theEvent, message, CPDialog, numItems, GroupHnd(cdevStorage));                {Handle a key event}
  266.                             HUnlock(Handle(cdevStorage));
  267.                         end;
  268.  
  269.                     cutDev, copyDev, pasteDev, clearDev: 
  270.                         begin
  271.                             HLock(Handle(cdevStorage));
  272.                             DoEdit(message, numItems, CPDialog, GroupHnd(cdevStorage));                            {Respond to an edit command}
  273.                             HUnlock(Handle(cdevStorage));
  274.                         end;
  275.  
  276.                     cursorDev: 
  277.                         begin
  278.                             HLock(Handle(cdevStorage));
  279.                             GetDItem(CPDialog, COMMLINE + numItems, dummykind, TempH, r);        {Get the rectangle of the command line}
  280.                             GetMouse(pt);                    {Get the mouse position}
  281.                             if PtInRect(pt, r) then        {If the mouse is in the text item, set the I-Beam cursor}
  282.                                 begin
  283.                                     IBeam := GetCursor(iBeamCursor);        {Get the I-Beam cursor}
  284.                                     SetCursor(IBeam^^);                        {Set it}
  285.                                 end
  286.                             else
  287.                                 InitCursor;                    {Otherwise set the arrow cursor}
  288.                             HUnlock(Handle(cdevStorage));
  289.                         end;
  290.  
  291.                     updateDev: 
  292.                         begin
  293.                             if GroupHnd(cdevStorage)^^.ModemPort then            {Find out which port is set}
  294.                                 WIcon := MICON                                            {Modem Port}
  295.                             else
  296.                                 WIcon := PICON;                                            {Printer Port}
  297.                             GetDItem(CPDialog, WIcon + numItems, DummyKind, TempH, r);        {Get the rect around the proper icon}
  298.                             InvertRect(r);                                                                {Hilite the icon}
  299.                         end;
  300.  
  301.                     nulDev: 
  302.                         ;                 {Just a desk accesory run event - basically useless}
  303.                     macDev: 
  304.                         ;                 {We aren't concerned with macDev since the 'mach' resource contains our machine requirements}
  305.                     undoDev: 
  306.                         ;                {Undo is not supported}
  307.  
  308.                 end;  {CASE message}
  309.  
  310.                 main := cdevStorage;        {If cdevStorage = -1, 0, or 1 then let the Control Panel put an error message up}
  311.             end;
  312.     end; {main}
  313.  
  314. {------------------------------------------------------------------------}
  315.     procedure ReadResources (var CommandLine: StringHandle; var ConfigHnd: SerConHnd);
  316.  
  317.         const
  318.             CONFIGID = -4033;    {MUST BE BETWEEN  -4048 & -4033 FOR NO INTERFERE WITH THE CONTROL PANELS RESOURCES}
  319.             COMMID = -4033;    {MUST BE BETWEEN  -4048 & -4033 FOR NO INTERFERE WITH THE CONTROL PANELS RESOURCES}
  320.         var
  321.             tempH: Handle;        {Temporary storage for reading the SERC Resource}
  322.  
  323.     begin
  324.         CommandLine := GetString(COMMID);                        {Get the command line resource}
  325.         tempH := GetResource('SERC', CONFIGID);                    {Get the serial configuration resource}
  326.         ConfigHnd := SerConHnd(TempH);                            {Typecast generic handle to one the cdev will understand}
  327.     end;
  328. {------------------------------------------------------------------------}
  329.  
  330.     procedure DecodeConfigResource (ConfigHnd: SerConHnd; var Baud, Par, StopB, DataB, Port: integer);
  331.  
  332.     begin
  333.         with ConfigHnd^^ do
  334.             begin
  335.                 Baud := integer(BAND(baudRateNPort, $0F));    {Extract the baud rate as a value the rest of the cdev will recognize}
  336.                 Port := integer(BAND(baudRateNPort, $F0));    {Extract the port to be used as a value the rest of the cdev will recognize}
  337.                 Par := integer(BAND(rest, $E0));                {Extract the parity value as a value the rest of the cdev will recognize}
  338.                 StopB := integer(BAND(rest, $1C));            {Extract the stop bits value as a value the rest of the cdev will recognize}
  339.                 DataB := integer(BAND(rest, $03));            {Extract the data bits value as a value the rest of the cdev will recognize}
  340.             end;
  341.     end;
  342. {------------------------------------------------------------------------}
  343.  
  344.     procedure SetButtonON (var ThisButton: ButtonRec; CPDialog: DialogPtr; numItems: integer);
  345.  
  346.         var
  347.             DummyKind: Integer;        {These are dummy variables for the GetDItem calls}
  348.             TempH: Handle;
  349.             r: Rect;
  350.  
  351.     begin
  352.         GetDItem(CPDialog, ThisButton.item + numItems, DummyKind, TempH, r);        {Get the handle to the button to be set}
  353.         SetCtlValue(ControlHandle(TempH), 1);                                {Turn the button on}
  354.     end;        {SetButtonON}
  355. {------------------------------------------------------------------------}
  356.  
  357.     procedure SetButtonOFF (var ThisButton: ButtonRec; CPDialog: DialogPtr; numItems: integer);
  358.  
  359.         var
  360.             DummyKind: Integer;        {These are dummy variables for the GetDItem calls}
  361.             TempH: Handle;
  362.             r: Rect;
  363.  
  364.     begin
  365.         GetDItem(CPDialog, ThisButton.item + numItems, DummyKind, TempH, r);        {Get the handle to the button to be set}
  366.         SetCtlValue(ControlHandle(TempH), 0);                                {Turn the button off}
  367.     end;        {SetButtonON}
  368. {------------------------------------------------------------------------}
  369.  
  370.     procedure SetUpButtons (var GroupRecord: GroupHnd; Baud, Par, StopB, DataB: integer);
  371.  
  372.     begin
  373.         with GroupRecord^^ do
  374.             begin
  375.                 Group1.Value := Baud;
  376.                 case Baud of                                            {Save the appropriate item number}
  377.                     BAUD12: 
  378.                         Group1.Item := G11200;        {If the baud rate is 1200, save the item number}
  379.                     BAUD24: 
  380.                         Group1.Item := G12400;        {If the baud rate is 2400, save the item number}
  381.                     BAUD96: 
  382.                         Group1.Item := G19600;        {If the baud rate is 9600, save the item number}
  383.                 end;
  384.  
  385.                 Group2.Value := Par;
  386.                 case Par of                                            {Save the appropriate item number}
  387.                     PARNONE: 
  388.                         Group2.Item := G2NO;            {If there is no parity, save the item number}
  389.                     PAREVEN: 
  390.                         Group2.Item := G2EVEN;            {If there is even parity, save the item number}
  391.                     PARODD: 
  392.                         Group2.Item := G2ODD;            {If there is odd parity, save the item number}
  393.                 end;
  394.  
  395.                 Group3.Value := StopB;
  396.                 case StopB of                                        {Save the appropriate item number}
  397.                     STOP1: 
  398.                         Group3.Item := G31;                {If there is 1 stop bit, save the item number}
  399.                     STOP12: 
  400.                         Group3.Item := G312;            {If there are 1.5 stop bits, save the item number}
  401.                     STOP2: 
  402.                         Group3.Item := G32;                {If there are 2 stop bits, set save the item number}
  403.                 end;
  404.  
  405.                 Group4.Value := DataB;
  406.                 case DataB of                                        {Save the appropriate item number}
  407.                     DAT7: 
  408.                         Group4.Item := G47;            {If there are 7 data bits, save the item number}
  409.                     DAT8: 
  410.                         Group4.Item := G48;            {If there are 8 data bits, save the item number}
  411.                 end;
  412.             end;        {With}
  413.     end;        {Set Up Buttons}
  414. {------------------------------------------------------------------------}
  415.  
  416.     procedure SetCommandLine (CPDialog: DialogPtr; CommandLine: StringHandle; numItems: integer);
  417.  
  418.         var
  419.             dummyKind: integer;                        {Used in GetDItem calls - just a dummy}
  420.             dummyRect: rect;                            {Used in GetDItem calls - just a dummy}
  421.             TempHandle: Handle;                        {A temporary handle to the command line dialog item}
  422.  
  423.     begin
  424.         GetDItem(CPDialog, COMMLINE + numItems, dummyKind, TempHandle, dummyRect);
  425.                             {Get a handle to the text item}
  426.  
  427.         SetIText(TempHandle, CommandLine^^);        {Set the text item to the command line read from the resource}
  428.  
  429.         SelIText(CPDialog, COMMLINE + numItems, 0, 999);
  430.                             {Select the command line so a carat will appear when editing}
  431.     end;        {Set Command Line}
  432. {------------------------------------------------------------------------}
  433.  
  434.     procedure CheckAndSetGroup1 (var Group1: ButtonRec; CPDialog: DialogPtr; ItemHit, numItems: Integer);
  435.  
  436.     begin
  437.         case ItemHit of
  438.             G11200: 
  439.                 begin
  440.                     Group1.Value := BAUD12;            {If the item hit was 1200 baud button set new value}
  441.                     SetButtonOFF(Group1, CPDialog, numItems);        {Turn Off the old button}
  442.                     Group1.item := ItemHit;                {Set the group state to hold the new item}
  443.                     SetButtonON(Group1, CPDialog, numItems);        {Turn ON the new button}
  444.                 end;
  445.             G12400: 
  446.                 begin
  447.                     Group1.Value := BAUD24;            {If the item hit was 2400 baud button set new value}
  448.                     SetButtonOFF(Group1, CPDialog, numItems);        {Turn Off the old button}
  449.                     Group1.item := ItemHit;                {Set the group state to hold the new item}
  450.                     SetButtonON(Group1, CPDialog, numItems);        {Turn ON the new button}
  451.                 end;
  452.             G19600: 
  453.                 begin
  454.                     Group1.Value := BAUD96;            {If the item hit was 9600 baud button set new value}
  455.                     SetButtonOFF(Group1, CPDialog, numItems);        {Turn Off the old button}
  456.                     Group1.item := ItemHit;                {Set the group state to hold the new item}
  457.                     SetButtonON(Group1, CPDialog, numItems);        {Turn ON the new button}
  458.                 end;
  459.         end;    {Case for Group1}
  460.     end;        {CheckAndSetGroup1}
  461. {------------------------------------------------------------------------}
  462.  
  463.     procedure CheckAndSetGroup2 (var Group2: ButtonRec; CPDialog: DialogPtr; ItemHit, numItems: Integer);
  464.  
  465.     begin
  466.         case ItemHit of
  467.             G2NO: 
  468.                 begin
  469.                     Group2.Value := PARNONE;            {If the item hit was No Parity button set new value}
  470.                     SetButtonOFF(Group2, CPDialog, numItems);        {Turn Off the old button}
  471.                     Group2.item := ItemHit;                {Set the group state to hold the new item}
  472.                     SetButtonON(Group2, CPDialog, numItems);        {Turn ON the new button}
  473.                 end;
  474.             G2EVEN: 
  475.                 begin
  476.                     Group2.Value := PAREVEN;            {If the item hit was Even Parity button set new value}
  477.                     SetButtonOFF(Group2, CPDialog, numItems);        {Turn Off the old button}
  478.                     Group2.item := ItemHit;                {Set the group state to hold the new item}
  479.                     SetButtonON(Group2, CPDialog, numItems);        {Turn ON the new button}
  480.                 end;
  481.             G2ODD: 
  482.                 begin
  483.                     Group2.Value := PARODD;                {If the item hit was Odd Parity button set new value}
  484.                     SetButtonOFF(Group2, CPDialog, numItems);        {Turn Off the old button}
  485.                     Group2.item := ItemHit;                {Set the group state to hold the new item}
  486.                     SetButtonON(Group2, CPDialog, numItems);        {Turn ON the new button}
  487.                 end;
  488.         end;    {Case for Group2}
  489.     end;        {CheckAndSetGroup2}
  490. {------------------------------------------------------------------------}
  491.  
  492.     procedure CheckAndSetGroup3 (var Group3: ButtonRec; CPDialog: DialogPtr; ItemHit, numItems: Integer);
  493.  
  494.     begin
  495.         case ItemHit of
  496.             G31: 
  497.                 begin
  498.                     Group3.Value := STOP1;                {If the item hit was 1 stop bit button set new value}
  499.                     SetButtonOFF(Group3, CPDialog, numItems);        {Turn Off the old button}
  500.                     Group3.item := ItemHit;                {Set the group state to hold the new item}
  501.                     SetButtonON(Group3, CPDialog, numItems);        {Turn ON the new button}
  502.                 end;
  503.             G312: 
  504.                 begin
  505.                     Group3.Value := STOP12;                {If the item hit was 1.5 stop bits button set new value}
  506.                     SetButtonOFF(Group3, CPDialog, numItems);        {Turn Off the old button}
  507.                     Group3.item := ItemHit;                {Set the group state to hold the new item}
  508.                     SetButtonON(Group3, CPDialog, numItems);        {Turn ON the new button}
  509.                 end;
  510.             G32: 
  511.                 begin
  512.                     Group3.Value := STOP2;                {If the item hit was 2 stop bits button set new value}
  513.                     SetButtonOFF(Group3, CPDialog, numItems);        {Turn Off the old button}
  514.                     Group3.item := ItemHit;                {Set the group state to hold the new item}
  515.                     SetButtonON(Group3, CPDialog, numItems);        {Turn ON the new button}
  516.                 end;
  517.         end;    {Case for Group3}
  518.     end;        {CheckAndSetGroup3}
  519. {------------------------------------------------------------------------}
  520.  
  521.     procedure CheckAndSetGroup4 (var Group4: ButtonRec; CPDialog: DialogPtr; ItemHit, numItems: Integer);
  522.  
  523.     begin
  524.         case ItemHit of
  525.             G47: 
  526.                 begin
  527.                     Group4.Value := DAT7;                {If the item hit was 7 data bits button set new value}
  528.                     SetButtonOFF(Group4, CPDialog, numItems);        {Turn Off the old button}
  529.                     Group4.item := ItemHit;                {Set the group state to hold the new item}
  530.                     SetButtonON(Group4, CPDialog, numItems);        {Turn ON the new button}
  531.                 end;
  532.             G48: 
  533.                 begin
  534.                     Group4.Value := DAT8;                {If the item hit was 8 data bits button set new value}
  535.                     SetButtonOFF(Group4, CPDialog, numItems);        {Turn Off the old button}
  536.                     Group4.item := ItemHit;                {Set the group state to hold the new item}
  537.                     SetButtonON(Group4, CPDialog, numItems);        {Turn ON the new button}
  538.                 end;
  539.         end;    {Case for Group4}
  540.     end;        {CheckAndSetGroup4}
  541. {------------------------------------------------------------------------}
  542.  
  543.     procedure DoClose (var cdevStorage: Longint);
  544.  
  545.         var
  546.             CommandLine: StringHandle;                {A handle to the command line read from the resource}
  547.             ConfigHnd: SerConHnd;                        {A handle to the serial configuration read from the 'SERC' resource}
  548.             Baud, Par, StopB, DataB, Port: integer;        {Used to hold values when working with decoded 'SERC' resource}
  549.  
  550.     begin
  551.         Hlock(Handle(cdevStorage));
  552.         ReadResources(CommandLine, ConfigHnd);
  553.                         {First read the resources into memory so we have current handles for writing}
  554.         HLock(Handle(CommandLine));                {Lock it down so it doesn't get trashed before we can write out}
  555.         HLock(Handle(ConfigHnd));                    {Lock it down so it doesn't get trashed before we can write out}
  556.         GetGroupValues(GroupHnd(cdevStorage), Baud, Par, StopB, DataB);                    {Get the current settings}
  557.         EncodeResource(ConfigHnd, Baud, Par, StopB, DataB, GroupHnd(cdevStorage)^^.ModemPort);
  558.                                     {Encode the resource so it can be written}
  559.         HUnLock(Handle(CommandLine));            {Unlock it now so we can change it}
  560.  
  561.         if ord(GroupHnd(cdevStorage)^^.CommandText[Length(GroupHnd(cdevStorage)^^.CommandText)]) <> 13 then
  562.             GroupHnd(cdevStorage)^^.CommandText := concat(GroupHnd(cdevStorage)^^.CommandText, Chr(13));
  563.                                 {If there isn't a <CR> at the end of the command line, put one on}
  564.  
  565.         SetString(CommandLine, GroupHnd(cdevStorage)^^.CommandText);                    {Set the new Command line}
  566.         HLock(Handle(CommandLine));                {Lock it down again so it doesn't get trashed before we can write out}
  567.         ChangedResource(Handle(CommandLine));                    {Mark resource as changed so it will be written out}
  568.         SaveResources(CommandLine, ConfigHnd);                                {Write out the resources}
  569.         HUnLock(Handle(CommandLine));            {Let it go now since we don't need it anymore}
  570.         HUnLock(Handle(ConfigHnd));                {Let it go now since we don't need it anymore}
  571.         HUnlock(Handle(cdevStorage));
  572.     end;
  573. {------------------------------------------------------------------------}
  574.  
  575.     procedure PinDialog (CPDialog: DialogPtr; theDialog: DialogPtr);
  576.  
  577.         var
  578.             CPLeft, CPBottom: integer;        {The left and bottom coordinates of the Control Panel dialog}
  579.             DTop, DLeft: integer;                {The new top and left coordinates of the error dialog - used in pinning it to the control panel}
  580.             pt: Point;                            {A point to hold the CPDialog's lower left corner}
  581.             SavePort: GrafPtr;                {The old port}
  582.  
  583.     begin
  584.         getPort(SavePort);                                {Get the old port}
  585.         CPLeft := CPDialog^.portrect.Left;                {Get the left edge of the control panel window}
  586.         CPBottom := CPDialog^.portrect.Bottom;        {Get the bottom edge of the control panel window}
  587.  
  588.         SetPt(pt, CPLeft, CPBottom);                    {Set a point to the lower left corner of the control panel's window}
  589.         LocalToGlobal(pt);                                {Change the point to gloabl coordinates}
  590.  
  591.         DLeft := pt.h + 15;                                                                        {Calculate the new left coordinate}
  592.         DTop := pt.v - 15 - (theDialog^.portrect.bottom - theDialog^.portrect.top);
  593.                                                                                                         {Calculate the new top coordinate}
  594.         MoveWindow(theDialog, DLeft, DTop, True);    {pin the error dialog to the bottom-left corner of the control panel window}
  595.         setport(savePort);                                {Set the port to the old port}
  596.  
  597.     end;
  598. {------------------------------------------------------------------------}
  599.  
  600.     procedure OutLineDefault (theDialog: DialogPtr);
  601.  
  602.         var
  603.             DummyKind: integer;            {A dummy used in GetDItem calls}
  604.             TempH: Handle;                    {A dummy used in GetDItem calls}
  605.             theRect: Rect;                    {The rect of the OK button}
  606.             thePen: PenState;                {A holding place for the old pen state}
  607.             SavePort: GrafPtr;                {The old port}
  608.  
  609.     begin
  610.         getPort(SavePort);                                {Get the old port}
  611.         setport(theDialog);                                {Set the port to theDialog}
  612.         GetDItem(theDialog, OK, DummyKind, TempH, theRect);        {Get the rectangle of the OK button}
  613.         GetPenState(thePen);                                            {Save the current pen state}
  614.         Pensize(3, 3);                                                    {Set the pen to 3 by 3 pixels}
  615.         InsetRect(theRect, -4, -4);                                        {Set the rectangle around the button}
  616.         FrameRoundRect(theRect, 16, 16);                                {Draw the outline}
  617.         SetPenState(thePen);                                            {Restore the old pen state}
  618.         SetPort(SavePort);                                {Set the old port}
  619.     end;
  620. {------------------------------------------------------------------------}
  621.  
  622.  
  623.     function ErrorCheck (Err: OSerr; CPDialog: DialogPtr): Boolean;
  624.  
  625.         var
  626.             tempstr: str255;                    {Used in unknown error message}
  627.             itemHit: integer;                    {The item that was hit in the error dialog}
  628.             ErrDialog: DialogPtr;                {The error dialog pointer}
  629.  
  630.     begin
  631.         ErrorCheck := False;                {Hopefully we won't have an error}
  632.         if Err <> noErr then
  633.             begin
  634.                 ErrorCheck := True;            {We had an error so let the calling routine know it}
  635.                 ErrDialog := GetNewDialog(ERRDLOG, nil, pointer(-1));        {Get the error dialog box}
  636.                 PinDialog(CPDialog, ErrDialog);            {Pin the dialog to the lower left corner of the control panel dialog}
  637.                 case Err of                                        {Set in the error dialog a message saying what error occurred}
  638.                     badUnitErr: 
  639.                         ParamText('Bad ref num', '', '', '');
  640.                     dInstErr: 
  641.                         ParamText('Driver Not Found', '', '', '');
  642.                     openErr: 
  643.                         ParamText('Cannot perform request', '', '', '');
  644.                     unitEmptyErr: 
  645.                         ParamText('Unit Bad ref num', '', '', '');
  646.                     dRemovErr: 
  647.                         ParamText('Attempt to remove an open driver', '', '', '');
  648.                     writErr: 
  649.                         ParamText('Driver cannot respond to write calls', '', '', '');
  650.                     NotOpenErr: 
  651.                         ParamText('Driver not open', '', '', '');
  652.                     otherwise
  653.                         begin
  654.                             numtostring(Err, TempStr);
  655.                             TempStr := concat('Unknown error # ', TempStr);    {An error not defined above occured - notify user of error number}
  656.                             ParamText(TempStr, '', '', '');
  657.                         end;        {Otherwise}
  658.                 end;            {CASE}
  659.                 SysBeep(3);                            {Beep like an alert}
  660.                 ShowWindow(ErrDialog);            {Show the window}
  661.                 OutLineDefault(ErrDialog);            {Outline the OK button - Item #1}
  662.                 repeat
  663.                     ModalDialog(nil, itemHit);
  664.                 until itemHit = 1;
  665.                 DisposDialog(ErrDialog);                {Get rid of the error dialog}
  666.             end;                {If error}
  667.     end;
  668. {------------------------------------------------------------------------}
  669.  
  670.     function SetSerialConfig (GroupRecord: GroupHnd): integer;
  671.  
  672.         var
  673.             Baud, Par, StopB, DataB: integer;            {Hold the values that will be added together for serial configuration}
  674. {*****N O T E:  These are not the same values that are used by our resource, but the actual toolbox values needed*****}
  675.  
  676.     begin
  677.         with GroupRecord^^ do
  678.             begin
  679.                 case Group1.Value of
  680.                     BAUD12: 
  681.                         Baud := Baud1200;        {If the baud rate is 1200, set the baud rate value for serial configuration}
  682.                     BAUD24: 
  683.                         Baud := Baud2400;        {If the baud rate is 2400, set the baud rate value for serial configuration}
  684.                     BAUD96: 
  685.                         Baud := Baud9600;        {If the baud rate is 9600, set the baud rate value for serial configuration}
  686.                 end;
  687.  
  688.                 case Group2.Value of
  689.                     PARNONE: 
  690.                         Par := NOParity;                {If there is no parity, set the parity value for serial configuration}
  691.                     PAREVEN: 
  692.                         Par := EVENParity;            {If there is even parity, set the parity value for serial configuration}
  693.                     PARODD: 
  694.                         Par := ODDParity;            {If there is odd parity, set the parity value for serial configuration}
  695.                 end;
  696.  
  697.                 case Group3.Value of
  698.                     STOP1: 
  699.                         StopB := Stop10;                {If there is 1 stop bit, set the Stop Bits value for serial configuration}
  700.                     STOP12: 
  701.                         StopB := Stop15;                {If there are 1.5 stop bits, set the Stop Bits value for serial configuration}
  702.                     STOP2: 
  703.                         StopB := stop20;                {If there are 2 stop bits, set the Stop Bits value for serial configuration}
  704.                 end;
  705.  
  706.                 case Group4.Value of
  707.                     DAT7: 
  708.                         DataB := Data7;                {If there are 7 data bits, set the Data Bits value for serial configuration}
  709.                     DAT8: 
  710.                         DataB := Data8;                {If there are 8 data bits, set the Data Bits value for serial configuration}
  711.                 end;
  712.             end;        {With}
  713.  
  714.         SetSerialConfig := Baud + Par + StopB + DataB;        {This is the actual serial configuration value sent to the modem}
  715.     end;
  716. {------------------------------------------------------------------------}
  717.  
  718.     procedure SendCommand (CPDialog: DialogPtr; var GroupRecord: GroupHnd);
  719.  
  720.         var
  721.             serConfig: integer;                {This is the serial port configuration value}
  722.             refnum: integer;                {This is the reference number for the modem serial out port}
  723.             Len: Longint;                    {The Length of the string}
  724.             Error: OSErr;                    {Will hold the error code if we have an error}
  725.             tempstr: str255;                {Will hold the command line}
  726.             TempLong: Longint;                {A temporary long integer used to hold the value of cdevStorage}
  727.  
  728.     begin
  729.         if GroupRecord^^.ModemPort then
  730.             Error := OpenDriver('.AOut', refnum)                                {Open the modem out port}
  731.         else
  732.             Error := OpenDriver('.BOut', refnum);                                {Open the printer out port}
  733.         if ErrorCheck(Error, CPDialog) then            {Check for an error}
  734.             exit(SendCommand);                            {If an error occurred exit SendCommand}
  735.         serConfig := SetSerialConfig(GroupRecord);                        {Set up configuration}
  736.         Error := SerReset(refnum, serConfig);                            {Set the configuration}
  737.         if ErrorCheck(Error, CPDialog) then            {Check for an error}
  738.             exit(SendCommand);                            {If an error occurred exit SendCommand}
  739.         tempStr := GroupRecord^^.CommandText;                            {Get the command line}
  740.         Len := length(tempStr);                                                {Get the length of the command}
  741.         if ord(tempStr[Len]) <> 13 then
  742.             begin
  743.                 tempStr := concat(tempStr, Chr(13));                    {If there isn't a <CR> at the end of the command line, put one on}
  744.                 Len := Len + 1;                                            {Add one to the length of the string since we added a <CR>}
  745.             end;
  746.  
  747.         Error := FSWrite(refNum, Len, @tempStr[1]);                    {Write the command line to the modem port}
  748.         if ErrorCheck(Error, CPDialog) then            {Check for an error}
  749.             exit(SendCommand);                            {If an error occurred exit SendCommand}
  750.         Error := CloseDriver(refNum);                                      {Close the port}
  751.         if ErrorCheck(Error, CPDialog) then            {Check for an error}
  752.             exit(SendCommand);                            {If an error occurred exit SendCommand}
  753.     end;
  754. {------------------------------------------------------------------------}
  755.  
  756.     procedure DoHit (var cdevStorage: Longint; var GroupRecord: GroupHnd; ItemHit: integer; CPDialog: DialogPtr; numItems: integer);
  757.  
  758.         var
  759.             MIconRect, PIconRect: Rect;            {The rectangle of the modem and printer icon}
  760.             DummyKind: integer;                    {A dummy used in GetDItem calls}
  761.             TempH: Handle;                            {A dummy used in GetDItem calls}
  762.  
  763.     begin
  764.         case ItemHit of
  765.             SENDNOW: 
  766.                 SendCommand(CPDialog, GroupRecord);
  767.  
  768.             MICON: 
  769.                 if not GroupRecord^^.ModemPort then
  770.                     begin
  771.                         GetDItem(CPDialog, MICON + numItems, DummyKind, TempH, MIconRect);
  772.                         GetDItem(CPDialog, PICON + numItems, DummyKind, TempH, PIconRect);
  773.                         InvertRect(MIconRect);        {If the modem icon was hit and it wasn't set already, hilite its icon and...}
  774.                         InvertRect(PIconRect);        {UnHilite the printer icon}
  775.                         GroupRecord^^.ModemPort := True;        {Set the new selected port}
  776.                     end;
  777.  
  778.             PICON: 
  779.                 if GroupRecord^^.ModemPort then
  780.                     begin
  781.                         GetDItem(CPDialog, MICON + numItems, DummyKind, TempH, MIconRect);
  782.                         GetDItem(CPDialog, PICON + numItems, DummyKind, TempH, PIconRect);
  783.                         InvertRect(PIconRect);        {If the printer icon was hit and it wasn't set already, hilite its icon and...}
  784.                         InvertRect(MIconRect);        {UnHilite the modem icon}
  785.                         GroupRecord^^.ModemPort := False;        {Set the new selected port}
  786.                     end;
  787.             otherwise
  788.                 begin
  789.                     with GroupRecord^^ do
  790.                         begin
  791.                             CheckAndSetGroup1(Group1, CPDialog, ItemHit, numItems);    {Check if Itemhit in Group 1 if so, set the new button}
  792.                             CheckAndSetGroup2(Group2, CPDialog, ItemHit, numItems);    {Check if Itemhit in Group 2 if so, set the new button}
  793.                             CheckAndSetGroup3(Group3, CPDialog, ItemHit, numItems);    {Check if Itemhit in Group 3 if so, set the new button}
  794.                             CheckAndSetGroup4(Group4, CPDialog, ItemHit, numItems);    {Check if Itemhit in Group 4 if so, set the new button}
  795.                         end;        {With}
  796.                 end;        {otherwise}
  797.         end;        {Case}
  798.     end;        {DoHit}
  799. {------------------------------------------------------------------------}
  800.  
  801.     procedure GetGroupValues (GroupRecord: GroupHnd; var Baud, Par, StopB, DataB: integer);
  802.  
  803.     begin
  804.         Baud := GroupRecord^^.Group1.Value;        {Set the baud value from the button record for Group 1}
  805.         Par := GroupRecord^^.Group2.Value;        {Set the parity value from the button record for Group 2}
  806.         StopB := GroupRecord^^.Group3.Value;        {Set the stop bits value from the button record for Group 3}
  807.         DataB := GroupRecord^^.Group4.Value;        {Set the data bits value from the button record for Group 4}
  808.     end;        {Get Group Values}
  809. {------------------------------------------------------------------------}
  810.  
  811.     procedure EncodeResource (var ConfigHnd: SerConHnd; Baud, Par, StopB, DataB: integer; ModemPort: Boolean);
  812.  
  813.     begin
  814.         ConfigHnd^^.baudRateNPort := SignedByte(Baud);                {Set the new baud rate into the configuration}
  815.         if ModemPort then
  816.             ConfigHnd^^.baudRateNPort := ConfigHnd^^.baudRateNPort + 16;        {Set the port to be used into the configuration}
  817.         ConfigHnd^^.rest := SignedByte(Par + StopB + DataB);    {Set the rest of the stuff in as the rest of the configuration}
  818.         ChangedResource(Handle(ConfigHnd));                {Mark the resource as changed so it will be written}
  819.     end;        {Encode Resource}
  820.  
  821. {------------------------------------------------------------------------}
  822.  
  823.  
  824.     procedure SaveResources (CommandLine: StringHandle; ConfigHnd: SerConHnd);
  825.  
  826.     begin
  827.         WriteResource(Handle(CommandLine));                {Write out the new command line}
  828.         WriteResource(Handle(ConfigHnd));                    {Write out the new configuration settings}
  829.     end;        {Save Resources}
  830. {------------------------------------------------------------------------}
  831.  
  832.     procedure StoreCommandLine (CPDialog: DialogPtr; CommandItem: integer; var GroupRecord: GroupHnd);
  833.  
  834.         var
  835.             dummyKind: Integer;        {Dummy variable used in GetDItem calls}
  836.             TempH: handle;                {Dummy variable used in GetDItem calls}
  837.             r: rect;                        {Dummy variable used in GetDItem calls}
  838.             TempStr: str255;            {A string to hold the command line text}
  839.  
  840.     begin
  841.         GetDItem(CPDialog, CommandItem, dummykind, TempH, r);        {Get a handle to the command line}
  842.         GetIText(TempH, TempSTR);                        {Get the command line from the dialog}
  843.  
  844.         GroupRecord^^.CommandText := TempSTR;        {Update our storage to hold the latest command line}
  845.     end;
  846. {------------------------------------------------------------------------}
  847.  
  848.     procedure DoKeyDown (var theEvent: EventRecord; var message: integer; CPDialog: DialogPtr; numItems: integer; var GroupRecord: GroupHnd);
  849.         var
  850.             tempChar: CHAR;            {Used in keyboard messages}
  851.             theKey: integer;            {Used in keyboard messages}
  852.             CommandItem: integer;    {The item number of the command line plus numItems}
  853.             theButton: Handle;             {Handle for GetDItem of SendNow Button}
  854.             dummy: integer;            {dummy kind for GetDItem }
  855.             dummyR: rect;                 {dummy rect for GetDItem }
  856.  
  857.     begin
  858.         tempChar := CHR(BAnd(theEvent.message, charCodeMask));        {Get the character}
  859.         if BAnd(theEvent.modifiers, cmdKey) <> 0 then                {Check for a command key equivalent}
  860.             begin { ******* handle as command key ****** }
  861.                 message := nulDev;
  862.                 theEvent.what := nullEvent;            {Erase the event so we don't get it again}
  863.                 case tempChar of                        {If there was a command key then set up the appropriate message}
  864.                     'S', 's': 
  865.                         begin
  866.                             GetDItem(CPDialog, SENDNOW + NumItems, dummy, theButton, dummyR);
  867.                             HiliteControl(ControlHandle(theButton), 1);                 { Flash the Button }
  868.                             SendCommand(CPDialog, GroupRecord);
  869.                             HiliteControl(ControlHandle(theButton), 0);
  870.                         end;
  871.                     'Z', 'z': 
  872.                         begin
  873.                             message := undoDev;{**undoDev is not supported this is only here for someone who wishes to use it**}
  874.                             DoEdit(message, numItems, CPDialog, GroupRecord);            {Send the new edit message to the edit handler}
  875.                         end;
  876.                     'X', 'x': 
  877.                         begin
  878.                             message := cutDev;
  879.                             DoEdit(message, numItems, CPDialog, GroupRecord);            {Send the new edit message to the edit handler}
  880.                         end;
  881.                     'C', 'c': 
  882.                         begin
  883.                             message := copyDev;
  884.                             DoEdit(message, numItems, CPDialog, GroupRecord);            {Send the new edit message to the edit handler}
  885.                         end;
  886.                     'V', 'v': 
  887.                         begin
  888.                             message := pasteDev;
  889.                             DoEdit(message, numItems, CPDialog, GroupRecord);            {Send the new edit message to the edit handler}
  890.                         end;
  891.                 end; {case}
  892.             end { ******* handle as command key ****** }
  893.         else
  894.             begin
  895.                 theKey := (BitAnd(theEvent.message, KeyCodeMask)) div 256;  { decode char }
  896.                 case theKey of        {Check the key for an edit function key on an extended keyboard}
  897.                     F1: 
  898.                         begin
  899.                             message := undoDev;{**undoDev is not supported this is only here for someone who wishes to use it**}
  900.                             theEvent.what := nullEvent;
  901.                             DoEdit(message, numItems, CPDialog, GroupRecord);
  902.                         end;
  903.                     F2: 
  904.                         begin
  905.                             message := cutDev;                    {Set the new message so the edit handler can take care of it}
  906.                             theEvent.what := nullEvent;            {Wipe out the event so the dialog manager will not handle function keys}
  907.                             DoEdit(message, numItems, CPDialog, GroupRecord);            {Send the new edit message to the edit handler}
  908.                         end;
  909.                     F3: 
  910.                         begin
  911.                             message := copyDev;                {Set the new message so the edit handler can take care of it}
  912.                             theEvent.what := nullEvent;            {Wipe out the event so the dialog manager will not handle function keys}
  913.                             DoEdit(message, numItems, CPDialog, GroupRecord);            {Send the new edit message to the edit handler}
  914.                         end;
  915.                     F4: 
  916.                         begin
  917.                             message := pasteDev;                {Set the new message so the edit handler can take care of it}
  918.                             theEvent.what := nullEvent;            {Wipe out the event so the dialog manager will not handle function keys}
  919.                             DoEdit(message, numItems, CPDialog, GroupRecord);            {Send the new edit message to the edit handler}
  920.                         end;
  921.                     otherwise
  922.                         begin
  923.                             CommandItem := numItems + COMMLINE;        {Create var parameter for DialogSelect}
  924.                             if ((tempChar >= 'a') and (tempChar <= 'z')) then                {If the character hit is in lowercase ...}
  925.                                 begin
  926.                                     tempChar := chr(ord(tempChar) - (ord('a') - ord('A')));    {Force the character to uppercase ...}
  927.                                     theEvent.message := longint(tempChar);                        {store the uppercase character in the event so DialogSelect will process it}
  928.                                 end;
  929.                             if (DialogSelect(theEvent, CPDialog, CommandItem) = TRUE) then    {Let the dialog manager handle a key event}
  930.                                 StoreCommandLine(CPDialog, CommandItem, GroupRecord);            {Update our storage to hold the new command line}
  931.                             theEvent.what := nullEvent;        {Wipe out the event so the dialog manager will not process the key since we already did}
  932.                         end;
  933.                 end;     {Case}
  934.             end;        {else}
  935.     end;
  936. {------------------------------------------------------------------------}
  937.  
  938.     procedure DoEdit (message, numItems: INTEGER; CPDialog: DialogPtr; var GroupRecord: GroupHnd);
  939.  
  940.     begin
  941.         case message of
  942.             cutDev: 
  943.                 DlgCut(CPDialog);            {If a cut message was received, do dialog cut}
  944.             copyDev: 
  945.                 DlgCopy(CPDialog);            {If a copy message was received, do dialog copy}
  946.             pasteDev: 
  947.                 DlgPaste(CPDialog);            {If a paste message was received, do dialog paste}
  948.             clearDev: 
  949.                 DlgDelete(CPDialog);            {If a clear message was received, do dialog clear}
  950.         end;
  951.         StoreCommandLine(CPDialog, numItems + COMMLINE, GroupRecord);            {Update our storage to hold the new command line}
  952.     end; {DoEditCommand}
  953.  
  954. end.  {ModemCDEV}